﻿#include <stdio.h>
#include <string.h>
#include "gtest/gtest.h"
#include "map.h"

namespace
{
    // 测试 fixture 类
    class MapTest : public ::testing::Test
    {
    protected:
        void SetUp() override
        {
            // 创建 Map 对象
            map = CreateMap(50000);
        }

        void TearDown() override
        {
            // 删除 Map 对象
            DeleteMap(map);
        }

        // Map 对象指针
        Map *map;

        struct vms
        {
            int a;
            int b;
            int c;
            int d;
        };
    };

    // Map 添加和获取键值对测试
    TEST_F(MapTest, PutAndGet)
    {
        int values[10000];
        uint32_t keys[10000];

        // 添加 1 万条键值对
        for (int i = 0; i < 10000; ++i)
        {
            values[i] = i;
            keys[i] = i;
            Put(map, keys[i], &values[i]);
        }

        // 验证键值对数量是否正确
        EXPECT_EQ(map->size, 50000);

        // 验证 get 函数是否能返回正确的 value
        for (int i = 0; i < 10000; ++i)
            EXPECT_EQ(*(int *)Get(map, keys[i]), values[i]);

        // 验证 put 函数是否能更新已有的键值对
        for (int i = 0; i < 10000; ++i)
        {
            values[i] *= 2;
            Put(map, keys[i], &values[i]);
            EXPECT_EQ(*(int *)Get(map, keys[i]), values[i]);
        }
    }

    // Map 迭代器测试
    TEST_F(MapTest, Iterator)
    {
        uint32_t keys[5];

        // 添加 5 条键值对
        for (int i = 0; i < 5; ++i)
        {
            vms *_vms = (vms *)malloc(sizeof(vms));
            _vms->a = i;
            _vms->b = i;
            _vms->c = i;
            _vms->d = i;
            keys[i] = i;
            Put(map, keys[i], _vms);
        }

        // 使用迭代器遍历整个 Map 并取出每一个值
        int count = 0;
        Iterator *it = CreateIterator(map);
        Node *node;
        while ((node = GetNextNode(it)) != NULL)
        {
            EXPECT_EQ(node->key, keys[count]);
            EXPECT_EQ(((vms *)node->value)->a, count);
            EXPECT_EQ(((vms *)node->value)->b, count);
            EXPECT_EQ(((vms *)node->value)->c, count);
            EXPECT_EQ(((vms *)node->value)->d, count);
            free(node->value); // 释放 value 内存
            ++count;
        }
        DeleteIterator(it);
        EXPECT_EQ(count, 5);
    }
}